<template>
  <view class="wrapper">
    <view class="handBtn">
      <button @click="retDraw" class="uploadBtn">重写</button>
      <button @click="subCanvas" class="subBtn">完成</button>
    </view>
    <view class="handCenter">
      <canvas class="handWriting" disable-scroll="true" @touchstart.stop="uploadScaleStart"
              @touchmove.stop="uploadScaleMove"
              @touchend.stop="uploadScaleEnd" canvas-id="handWriting">
      </canvas>
    </view>
    <view class="handRight">
      <view class="handTitle">手写板</view>
    </view>
  </view>
</template>

<script setup>
import {uploadImageBase64} from "../../../api/module/common.js"
import {userContractSign} from "../../../api/module/contract.js"
import {reactive, ref} from 'vue'
import {onLoad, onShow} from "@dcloudio/uni-app";
import {authentication, jump} from "../../../utils/contract/isAuthentication.js"
import {useStore} from 'vuex';

const store = useStore()
const data = {
  member_seal_image: '',
  member_contract_id: 0,
  signer_type: 'self',
};

const show = ref(false)
const id = ref(0)
const canvasName = ref('handWriting')
let ctx = reactive(null)
const canvasWidth = ref(0)
const canvasHeight = ref(0)
const transparent = ref(1)// 透明度
const selectColor = ref('black')
const lineColor = ref('#1A1A1A')
const lineSize = ref(1.5)
const lineMin = ref(0.5)
const lineMax = ref(4)
const pressure = ref(1)
const smoothness = ref(60)
let currentPoint = reactive({})
let currentLine = reactive([])
const firstTouch = ref(true)
const radius = ref(1) //画圆的半径
let cutArea = reactive({top: 0, right: 0, bottom: 0, left: 0}) //裁剪区域
let bethelPoint = reactive([])//保存所有线条 生成的贝塞尔点；
let lastPoint = reactive({})
let chirography = reactive([])//笔迹
let currentChirography = reactive({})//当前笔迹
const signImg = ref('signImg')
const annex_file = ref([]);

let linePrack = reactive([])//划线轨迹 , 生成线条的实际点
onLoad((options) => {

  if (typeof (options.annex_file) == 'string') {
    annex_file.value = options.annex_file.split(',')
  }
  data.signer_type = options.signer_type;
  id.value = options.id
  data.member_contract_id = options.id;
  ctx = wx.createCanvasContext(canvasName.value)
  var query = wx.createSelectorQuery();
  query.select('.handCenter').boundingClientRect(rect => {
    canvasWidth.value = rect.width,
        canvasHeight.value = rect.height
    /* 将canvas背景设置为 白底，不设置  导出的canvas的背景为透明 */
    setCanvasBg('#fff');
  }).exec();
})
// 笔迹开始
const uploadScaleStart = (e) => {
  if (e.type != 'touchstart') return false;
  ctx.setFillStyle(lineColor.value);  // 初始线条设置颜色
  ctx.setGlobalAlpha(transparent.value);  // 设置半透明
  let newcurrentPoint = {
    x: e.touches[0].clientX - 50,
    y: e.touches[0].clientY - 14
  }
  let newcurrentLine = currentLine;
  newcurrentLine.unshift({
    time: new Date().getTime(),
    dis: 0,
    x: newcurrentPoint.x,
    y: newcurrentPoint.y
  })
  currentPoint = newcurrentPoint
  if (firstTouch) {
    cutArea = {top: currentPoint.y, right: currentPoint.x, bottom: currentPoint.y, left: currentPoint.x}
    firstTouch.value = false
  }
  pointToLine(newcurrentLine);
}
// 笔迹移动
const uploadScaleMove = (e) => {
  if (e.type != 'touchmove') return false;
  if (e.cancelable) {
    // 判断默认行为是否已经被禁用
    if (!e.defaultPrevented) {
      e.preventDefault();
    }
  }
  let point = {
    x: e.touches[0].clientX - 50,
    y: e.touches[0].clientY - 14
  }
  //测试裁剪
  if (point.y < cutArea.top) {
    cutArea.top = point.y;
  }
  if (point.y < 0) cutArea.top = 0;

  if (point.x > cutArea.right) {
    cutArea.right = point.x;
  }
  if (canvasWidth - point.x <= 0) {
    cutArea.right = canvasWidth;
  }
  if (point.y > cutArea.bottom) {
    cutArea.bottom = point.y;
  }
  if (canvasHeight - point.y <= 0) {
    cutArea.bottom = canvasHeight;
  }
  if (point.x < cutArea.left) {
    cutArea.left = point.x;
  }
  if (point.x < 0) cutArea.left = 0;

  lastPoint = currentPoint,
      currentPoint = point
  let newcurrentLine = currentLine
  newcurrentLine.unshift({
    time: new Date().getTime(),
    dis: distance(currentPoint, lastPoint),
    x: point.x,
    y: point.y
  })
  // this.setData({
  //   currentLine
  // })
  pointToLine(newcurrentLine);
}
// 笔迹结束
const uploadScaleEnd = (e) => {
  if (e.type != 'touchend') return 0;
  let point = {
    x: e.changedTouches[0].clientX - 50,
    y: e.changedTouches[0].clientY - 10
  }
  // this.setData({
  lastPoint.value = currentPoint,
      currentPoint = point
  // })
  let newcurrentLine = currentLine
  newcurrentLine.unshift({
    time: new Date().getTime(),
    dis: distance(newcurrentLine, lastPoint),
    x: point.x,
    y: point.y
  })
  // this.setData({
  //   currentLine
  // })
  if (currentLine.length > 2) {
    var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
    //$("#info").text(info.toFixed(2));
  }
  //一笔结束，保存笔迹的坐标点，清空，当前笔迹
  //增加判断是否在手写区域；
  pointToLine(newcurrentLine);
  var currentChirography = {
    lineSize: lineSize,
    lineColor: lineColor
  };
  let newchirography = chirography
  newchirography.unshift(currentChirography);
  chirography = newchirography
  let newlinePrack = linePrack
  newlinePrack.unshift(currentLine);
  linePrack = newlinePrack
  currentLine = []
}
const retDraw = () => {
  ctx.clearRect(0, 0, 700, 730)
  ctx.draw();
  //设置canvas背景
  setCanvasBg("#fff");
}

//画两点之间的线条；参数为:line，会绘制最近的开始的两个点；
const pointToLine = (line) => {
  calcBethelLine(line);
  return;
}
//计算插值的方式；
const calcBethelLine = (line) => {
  if (line.length <= 1) {
    line[0].r = radius.value;
    return;
  }
  let x0, x1, x2, y0, y1, y2, r0, r1, r2, len, lastRadius, dis = 0, time = 0, curveValue = 0.5;
  if (line.length <= 2) {
    x0 = line[1].x
    y0 = line[1].y
    x2 = line[1].x + (line[0].x - line[1].x) * curveValue;
    y2 = line[1].y + (line[0].y - line[1].y) * curveValue;
    //x2 = line[1].x;
    //y2 = line[1].y;
    x1 = x0 + (x2 - x0) * curveValue;
    y1 = y0 + (y2 - y0) * curveValue;
    ;

  } else {
    x0 = line[2].x + (line[1].x - line[2].x) * curveValue;
    y0 = line[2].y + (line[1].y - line[2].y) * curveValue;
    x1 = line[1].x;
    y1 = line[1].y;
    x2 = x1 + (line[0].x - x1) * curveValue;
    y2 = y1 + (line[0].y - y1) * curveValue;
  }
  //从计算公式看，三个点分别是(x0,y0),(x1,y1),(x2,y2) ；(x1,y1)这个是控制点，控制点不会落在曲线上；实际上，这个点还会手写获取的实际点，却落在曲线上
  len = distance({x: x2, y: y2}, {x: x0, y: y0});
  lastRadius = radius.value;
  for (let n = 0; n < line.length - 1; n++) {
    dis += line[n].dis;
    time += line[n].time - line[n + 1].time;
    if (dis > smoothness) break;
  }
  radius.value = Math.min(time / len * pressure.value + lineMin.value, lineMax.value) * lineSize.value
  line[0].r = radius.value;
  //计算笔迹半径；
  if (line.length <= 2) {
    r0 = (lastRadius + radius) / 2;
    r1 = r0;
    r2 = r1;
    //return;
  } else {
    r0 = (line[2].r + line[1].r) / 2;
    r1 = line[1].r;
    r2 = (line[1].r + line[0].r) / 2;
  }
  let n = 5;
  let point = [];
  for (let i = 0; i < n; i++) {
    let t = i / (n - 1);
    let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
    let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
    let r = lastRadius + (radius.value - lastRadius) / n * i;

    point.push({x: x, y: y, r: r});
    if (point.length == 3) {
      let a = ctaCalc(point[0].x, point[0].y, point[0].r, point[1].x, point[1].y, point[1].r, point[2].x, point[2].y, point[2].r);
      a[0].color = lineColor.value;
      bethelDraw(a, 1);
      point = [{x: x, y: y, r: r}];
    }
  }
  currentLine = line
}
//求两点之间距离
const distance = (a, b) => {
  let x = b.x - a.x;
  let y = b.y - a.y;
  return Math.sqrt(x * x + y * y);
}
const ctaCalc = (x0, y0, r0, x1, y1, r1, x2, y2, r2) => {
  let a = [], vx01, vy01, norm, n_x0, n_y0, vx21, vy21, n_x2, n_y2;
  vx01 = x1 - x0;
  vy01 = y1 - y0;
  norm = Math.sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001) * 2;
  vx01 = vx01 / norm * r0;
  vy01 = vy01 / norm * r0;
  n_x0 = vy01;
  n_y0 = -vx01;
  vx21 = x1 - x2;
  vy21 = y1 - y2;
  norm = Math.sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001) * 2;
  vx21 = vx21 / norm * r2;
  vy21 = vy21 / norm * r2;
  n_x2 = -vy21;
  n_y2 = vx21;
  a.push({mx: x0 + n_x0, my: y0 + n_y0, color: "#1A1A1A"});
  a.push({c1x: x1 + n_x0, c1y: y1 + n_y0, c2x: x1 + n_x2, c2y: y1 + n_y2, ex: x2 + n_x2, ey: y2 + n_y2});
  a.push({
    c1x: x2 + n_x2 - vx21,
    c1y: y2 + n_y2 - vy21,
    c2x: x2 - n_x2 - vx21,
    c2y: y2 - n_y2 - vy21,
    ex: x2 - n_x2,
    ey: y2 - n_y2
  });
  a.push({c1x: x1 - n_x2, c1y: y1 - n_y2, c2x: x1 - n_x0, c2y: y1 - n_y0, ex: x0 - n_x0, ey: y0 - n_y0});
  a.push({
    c1x: x0 - n_x0 - vx01,
    c1y: y0 - n_y0 - vy01,
    c2x: x0 + n_x0 - vx01,
    c2y: y0 + n_y0 - vy01,
    ex: x0 + n_x0,
    ey: y0 + n_y0
  });
  a[0].mx = a[0].mx.toFixed(1);
  a[0].mx = parseFloat(a[0].mx);
  a[0].my = a[0].my.toFixed(1);
  a[0].my = parseFloat(a[0].my);
  for (let i = 1; i < a.length; i++) {
    a[i].c1x = a[i].c1x.toFixed(1);
    a[i].c1x = parseFloat(a[i].c1x);
    a[i].c1y = a[i].c1y.toFixed(1);
    a[i].c1y = parseFloat(a[i].c1y);
    a[i].c2x = a[i].c2x.toFixed(1);
    a[i].c2x = parseFloat(a[i].c2x);
    a[i].c2y = a[i].c2y.toFixed(1);
    a[i].c2y = parseFloat(a[i].c2y);
    a[i].ex = a[i].ex.toFixed(1);
    a[i].ex = parseFloat(a[i].ex);
    a[i].ey = a[i].ey.toFixed(1);
    a[i].ey = parseFloat(a[i].ey);
  }
  return a;
}
const bethelDraw = (point, is_fill, color) => {
  ctx.beginPath();
  ctx.moveTo(point[0].mx, point[0].my);
  if (undefined != color) {
    ctx.setFillStyle(color);
    ctx.setStrokeStyle(color);
  } else {
    ctx.setFillStyle(point[0].color);
    ctx.setStrokeStyle(point[0].color);
  }
  for (let i = 1; i < point.length; i++) {
    ctx.bezierCurveTo(point[i].c1x, point[i].c1y, point[i].c2x, point[i].c2y, point[i].ex, point[i].ey);
  }
  ctx.stroke();
  if (undefined != is_fill) {
    ctx.fill(); //填充图形 ( 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序 )
  }
  ctx.draw(true)
}
const selectColorEvent = (event) => {
  var color = event.currentTarget.dataset.colorValue;
  var colorSelected = event.currentTarget.dataset.color;
  this.setData({
    selectColor: colorSelected,
    lineColor: color
  })
}
// 设置背景函数
//设置canvas背景色  不设置  导出的canvas的背景为透明
//@params：字符串  color
const setCanvasBg = (color) => {
  /* 将canvas背景设置为 白底，不设置  导出的canvas的背景为透明 */
  //rect() 参数说明  矩形路径左上角的横坐标，左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
  //这里是 canvasHeight - 4 是因为下边盖住边框了，所以手动减了写
  ctx.rect(0, 0, canvasWidth, canvasHeight - 4);
  // ctx.setFillStyle('red')
  ctx.setFillStyle(color)
  ctx.fill()  //设置填充
  ctx.draw()    //开画
}
//保存到相册
const saveCanvasAsImg = () => {
  wx.canvasToTempFilePath({
    canvasId: 'handWriting',
    fileType: 'png',
    quality: 1, //图片质量
    success(res) {
      // console.log(res.tempFilePath, 'canvas生成图片地址');
      wx.saveImageToPhotosAlbum({
        filePath: res.tempFilePath,
        success(res) {
          wx.showToast({
            title: '已保存到相册',
            duration: 2000
          });

        }
      })
    }
  })
}

// 完成  导出图片
const base64 = (url, type) => {
  return new Promise((resolve, reject) => {
    wx.getFileSystemManager().readFile({
      filePath: url,
      encoding: 'base64',
      success(res) {
        resolve(res.data)
      },
      fail() {
        reject()
      }
    })
  })
}
const subCanvas = () => {
  // if(!currentLine.length){
  // 	 uni.showToast({
  // 	 	title:'请签署',
  // 		icon:'none'
  // 	 })
  // 	 return
  // }
  // show.value = true
  ctx.draw(false, wx.canvasToTempFilePath({
        canvasId: 'handWriting',
        fileType: 'png',
        quality: 1, //图片质量
        success: (res) => {
          let url = res.tempFilePath
          console.log(url)
          base64(url, 'png').then(res => {
            // show.value = true
            uploadImage(res)
          })

        },
        fail() {
          wx.showToast({
            title: '导出失败',
            icon: 'none',
            duration: 2000
          })
        }
      })
  )
}
const submit = () => {

  uni.showModal({
    title: '签署密码',
    content: '',
    editable: true, //是否显示输入框
    placeholderText: '请输入签署密码', //输入框提示内容
    confirmText: '确认',
    cancelText: '取消',
    success: (res) => {
      if (res.confirm) {
        let params = {
          member_contract_id: id.value,
          member_seal_id: '',
          member_seal_image: data.member_seal_image,
          password: res.content,
          annex_file: annex_file.value,
          signer_type: data.signer_type,
        }
        userContractSign(params).then(result => {
          if (res.status_code == 501) {
            jump(store.state.userType)
          }
          uni.redirectTo({
            url: '/pages/contract/enterprise/detail?member_contract_id=' + data.member_contract_id,
            animationType: 'pop-in',
            animationDuration: 200
          });
        })

      }
    }
  })
}
const uploadImage = (url) => {
  let uploadParams = {
    ext: 'png',
    content: url,
    org_name: new Date().getTime() + '.png',
    turn: 90,
  }

  uploadImageBase64(uploadParams).then(res => {
    // show.value = true
    data.member_seal_image = res.url;
    submit()
  })
}
</script>

<style lang="scss" src="/static/css/contract/signPage.scss" scoped></style>